﻿// Copyright (c) Inossem. All rights reserved.
// Licensed under the LGPL-3.0 license. See LICENSE file in the project root for full license information.
using DWF.Studio.Custom;
using DWF.Studio.ISerivces;
using DWF.Studio.Models;
using DWF.Studio.Models.Enum;
using DWF.Studio.Project;
using DWF.Studio.Services;
using Microsoft.Scripting.Utils;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using WpfMessageBoxLibrary;

namespace DWF.Studio.Views
{
    /// <summary>
    /// WindowProjectIParams.xaml 的交互逻辑
    /// </summary>
    public partial class WindowProjectParams : INotifyPropertyChanged
    {
        private ProjectManager _projectManager = null;

        private IProjectParamDetailSerivce _projectParamDetailSerivce = null;

        private ObservableCollection<ProjectParam> _obsParams = new ObservableCollection<ProjectParam>();
        private int sort = 0;

        public WindowProjectParams()
        {
            InitializeComponent();
            if (!DesignerProperties.GetIsInDesignMode(this))
            {
                init();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged
        {
            add
            {
                ((INotifyPropertyChanged)_obsParams).PropertyChanged += value;
            }

            remove
            {
                ((INotifyPropertyChanged)_obsParams).PropertyChanged -= value;
            }
        }

        private void init()
        {
            _projectParamDetailSerivce = new ProjectParamDetailSerivce();
            _projectManager = ProjectManager.Instance;

            var projectInfo = _projectManager.CurrentProject;

            var projectParam = _projectParamDetailSerivce.GetProjectParamDetail();

            projectParam.Input.ToList().ForEach(p => _obsParams.Add(new ProjectParam() {
                Name = p.Name,
                Value = p.Value,
                ParamType =p.ParamType,
                Description=p.Description,
                InOrOut="Input"
            }));
            projectParam.Output.ToList().ForEach(p => _obsParams.Add(new ProjectParam()
            {
                Name = p.Name,
                Value = p.Value,
                ParamType = p.ParamType,
                Description = p.Description,
                InOrOut = "Output"
            }));

            this.windowProjectIparamsGrid.ItemsSource = null;
            this.windowProjectIparamsGrid.ItemsSource = _obsParams;
        }

        /// <summary>
        /// 删除行
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnDel_Click(object sender, RoutedEventArgs e)
        {
            if (this.windowProjectIparamsGrid.SelectedItem.ToString() != "{NewItemPlaceholder}")
            {
                _obsParams.Remove(this.windowProjectIparamsGrid.SelectedItem as ProjectParam);
            }
        }

        //保存.
        private void btnParams_Click(object sender, RoutedEventArgs e)
        {
            var projectParams = new List<ProjectParam>();
            
            foreach (var item in windowProjectIparamsGrid.Items)
            {
                if (item != null && item.ToString() != "{NewItemPlaceholder}")
                {
                    var projectParam = item as ProjectParam;
                    
                    DataGridTemplateColumn inOrOutTemplate = windowProjectIparamsGrid.Columns[1] as DataGridTemplateColumn;
                    DataGridTemplateColumn paramsTypeTemplate = windowProjectIparamsGrid.Columns[2] as DataGridTemplateColumn;
                    FrameworkElement inOrOutElement = inOrOutTemplate.GetCellContent(item);
                    FrameworkElement paramsTypeElement = paramsTypeTemplate.GetCellContent(item);
                    if (inOrOutElement == null || paramsTypeElement == null)
                        return;
                    ComboBox inOrOutComboBox = inOrOutTemplate.CellTemplate.FindName("inOrOut", inOrOutElement) as ComboBox;
                    ComboBox paramsTypeComboBox = paramsTypeTemplate.CellTemplate.FindName("paramsType", paramsTypeElement) as ComboBox;
                    projectParam.InOrOut = inOrOutComboBox.Text;
                    switch (paramsTypeComboBox.Text)
                    {
                        case "Number": projectParam.ParamType = EProjectParamType.Number;break;
                        case "Boolean": projectParam.ParamType = EProjectParamType.Boolean; break;
                        case "String": projectParam.ParamType = EProjectParamType.String ; break;
                        case "File": projectParam.ParamType = EProjectParamType.File; break;
                    }
                    if (string.IsNullOrWhiteSpace(projectParam.Name))
                    {
                        var msgProperties = new WpfMessageBoxProperties()
                        {
                            Button = MessageBoxButton.OK,
                            ButtonOkText = LocalizationProvider.GetLocalizedString("MessageBox_Button_Ok"),
                            Image = MessageBoxImage.Warning,
                            Text = LocalizationProvider.GetLocalizedString("WindowProjectParams_MsgBox_NameEmpty"),
                            Title = LocalizationProvider.GetLocalizedString("WindowCreateProject_MsgBox_Caption_Create_NameValidate"),
                        };
                        WpfMessageBox.Show(this, ref msgProperties);
                        return;
                    }
                    if (isNumber(projectParam.Name.Substring(0, 1))|| Regex.IsMatch(projectParam.Name, "[~!@#$%^&*()=+[\\]{}''\";/?,><`|！·￥…—（）\\-、；：。，》《]")|| projectParam.Name.Contains("\\"))
                    {
                        var msgProperties = new WpfMessageBoxProperties()
                        {
                            Button = MessageBoxButton.OK,
                            ButtonOkText = LocalizationProvider.GetLocalizedString("MessageBox_Button_Ok"),
                            Image = MessageBoxImage.Warning,
                            Text = LocalizationProvider.GetLocalizedString("WindowProjectParams_MsgBox_NameError"),
                            Title = LocalizationProvider.GetLocalizedString("WindowCreateProject_MsgBox_Caption_Create_NameValidate"),
                        };
                        WpfMessageBox.Show(this, ref msgProperties);
                        return;
                    }
                    
                    if (projectParam.InOrOut == "Input")
                    {
                        switch (projectParam.ParamType)
                        {
                            case EProjectParamType.Number:
                                if (!isNumber(projectParam.Value))
                                {
                                    var msgProperties = new WpfMessageBoxProperties()
                                    {
                                        Button = MessageBoxButton.OK,
                                        ButtonOkText = LocalizationProvider.GetLocalizedString("MessageBox_Button_Ok"),
                                        Image = MessageBoxImage.Warning,
                                        Text = string.Format(LocalizationProvider.GetLocalizedString("WindowProjectParams_MsgBox_ValueErrorType"), projectParam.Name),
                                        Title = LocalizationProvider.GetLocalizedString("WindowCreateProject_MsgBox_Caption_Create_NameValidate"),
                                    };
                                    WpfMessageBox.Show(this, ref msgProperties);
                                    return;
                                }
                                break;
                            case EProjectParamType.Boolean:
                                if (projectParam.Value.ToLower() != "true" && projectParam.Value.ToLower() != "false")
                                {
                                    var msgProperties = new WpfMessageBoxProperties()
                                    {
                                        Button = MessageBoxButton.OK,
                                        ButtonOkText = LocalizationProvider.GetLocalizedString("MessageBox_Button_Ok"),
                                        Image = MessageBoxImage.Warning,
                                        Text = string.Format(LocalizationProvider.GetLocalizedString("WindowProjectParams_MsgBox_ValueErrorType"), projectParam.Name),
                                        Title = LocalizationProvider.GetLocalizedString("WindowCreateProject_MsgBox_Caption_Create_NameValidate"),
                                    };
                                    WpfMessageBox.Show(this, ref msgProperties);
                                    return;
                                }
                                break;
                            case EProjectParamType.String:
                                break;
                            case EProjectParamType.File:
                                break;
                        }
                        projectParams.Add(projectParam);
                    }
                    else if (projectParam.InOrOut == "Output")
                    {
                        switch (projectParam.ParamType)
                        {
                            case EProjectParamType.Number:
                                if (!isNumber(projectParam.Value))
                                {
                                    var msgProperties = new WpfMessageBoxProperties()
                                    {
                                        Button = MessageBoxButton.OK,
                                        ButtonOkText = LocalizationProvider.GetLocalizedString("MessageBox_Button_Ok"),
                                        Image = MessageBoxImage.Warning,
                                        Text = string.Format(LocalizationProvider.GetLocalizedString("WindowProjectParams_MsgBox_ValueErrorType"), projectParam.Name),
                                        Title = LocalizationProvider.GetLocalizedString("WindowCreateProject_MsgBox_Caption_Create_NameValidate"),
                                    };
                                    WpfMessageBox.Show(this, ref msgProperties);
                                    return;
                                }
                                break;
                            case EProjectParamType.Boolean:
                                if (projectParam.Value.ToLower() != "true" && projectParam.Value.ToLower() != "false")
                                {
                                    var msgProperties = new WpfMessageBoxProperties()
                                    {
                                        Button = MessageBoxButton.OK,
                                        ButtonOkText = LocalizationProvider.GetLocalizedString("MessageBox_Button_Ok"),
                                        Image = MessageBoxImage.Warning,
                                        Text = string.Format(LocalizationProvider.GetLocalizedString("WindowProjectParams_MsgBox_ValueErrorType"), projectParam.Name),
                                        Title = LocalizationProvider.GetLocalizedString("WindowCreateProject_MsgBox_Caption_Create_NameValidate"),
                                    };
                                    WpfMessageBox.Show(this, ref msgProperties);
                                    return;
                                }
                                break;
                            case EProjectParamType.String:
                                break;
                            case EProjectParamType.File:
                                break;
                        }
                        projectParams.Add(projectParam);
                    }
                }
            }
            if (projectParams.Where(o=>o.InOrOut=="Input").Count() > 10|| projectParams.Where(o => o.InOrOut == "Output").Count()>10)//每个方向参数不可大于10个
            {
                var msgProperties = new WpfMessageBoxProperties()
                {
                    Button = MessageBoxButton.OK,
                    ButtonOkText = LocalizationProvider.GetLocalizedString("MessageBox_Button_Ok"),
                    Image = MessageBoxImage.Warning,
                    Text = LocalizationProvider.GetLocalizedString("WindowProjectParams_MsgBox_InOutPutEnough"),
                    Title = LocalizationProvider.GetLocalizedString("WindowCreateProject_MsgBox_Caption_Create_NameValidate"),
                };

                WpfMessageBox.Show(this, ref msgProperties);
                return;
            }

            if (projectParams.GroupBy(p => p.Name).Where(i => i.Count() > 1).Count() > 0)//参数名重复
            {
                var msgProperties = new WpfMessageBoxProperties()
                {
                    Button = MessageBoxButton.OK,
                    ButtonOkText = LocalizationProvider.GetLocalizedString("MessageBox_Button_Ok"),
                    Image = MessageBoxImage.Warning,
                    Text = LocalizationProvider.GetLocalizedString("WindowProjectParams_MsgBox_NameRepeat"),
                    Title = LocalizationProvider.GetLocalizedString("WindowCreateProject_MsgBox_Caption_Create_NameValidate"),
                };

                WpfMessageBox.Show(this, ref msgProperties);
                return;
            }
            var projectParamList = _projectParamDetailSerivce.GetProjectParamDetail();
            var paramsList = new List<ProjectParam>();
            projectParamList.Input.ToList().ForEach(p => paramsList.Add(new ProjectParam()
            {
                Name = p.Name,
                Value = p.Value,
                ParamType = p.ParamType,
                Description = p.Description,
                InOrOut = "Input"
            }));
            projectParamList.Output.ToList().ForEach(p => paramsList.Add(new ProjectParam()
            {
                Name = p.Name,
                Value = p.Value,
                ParamType = p.ParamType,
                Description = p.Description,
                InOrOut = "Output"
            }));
            var changeParams = new List<ProjectParam>();
            projectParams.ForEach(o => changeParams.Add(o));
            foreach (var item in paramsList)
            {
                changeParams.Remove(changeParams.Where(o => o.Name == item.Name 
                && o.Value == item.Value
                && o.ParamType == item.ParamType 
                && o.InOrOut == item.InOrOut).FirstOrDefault());
            }
            
            if (changeParams.Count>0)
            {
                _projectParamDetailSerivce.SetChangeParam(changeParams);
            }
            projectParamList.Input = projectParams.Where(o => o.InOrOut == "Input").ToList();
            projectParamList.Output = projectParams.Where(o => o.InOrOut == "Output").ToList();
            _projectParamDetailSerivce.SaveProjectParamDetail(projectParamList);
            this.Close();
        }
        //取消
        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }
        private bool isNumber(string value)
        {
            decimal isDecimal;
            var str=Decimal.TryParse(value,out isDecimal);
            return str;
        }
        private bool isFile(string value)
        {
            Regex rex = new Regex(@"(http|https|ftp|ftps)://(?<domain>[^(:|/]*)");
            if (rex.IsMatch(value))
                return true;
            else
                return false;
        }

        private void btnAdd_Click(object sender, RoutedEventArgs e)
        {
            int input, output; input = output = 0;
            foreach (var item in windowProjectIparamsGrid.Items)
            {
                if (item != null && item.ToString() != "{NewItemPlaceholder}")
                {
                    var projectParam = item as ProjectParam;
                    DataGridTemplateColumn inOrOutTemplate = windowProjectIparamsGrid.Columns[1] as DataGridTemplateColumn;
                    FrameworkElement inOrOutElement = inOrOutTemplate.GetCellContent(item);
                    ComboBox inOrOutComboBox = inOrOutTemplate.CellTemplate.FindName("inOrOut", inOrOutElement) as ComboBox;
                    if (inOrOutComboBox.Text == "Input")input++;
                    else if (inOrOutComboBox.Text == "Output")output++;
                }
            }
            if (windowProjectIparamsGrid.Items.Count>=20 || input>10|| output>10)//每个方向参数不可大于10个
            {
                var msgProperties = new WpfMessageBoxProperties()
                {
                    Button = MessageBoxButton.OK,
                    ButtonOkText = LocalizationProvider.GetLocalizedString("MessageBox_Button_Ok"),
                    Image = MessageBoxImage.Warning,
                    Text = LocalizationProvider.GetLocalizedString("WindowProjectParams_MsgBox_InOutPutEnough"),
                    Title = LocalizationProvider.GetLocalizedString("WindowCreateProject_MsgBox_Caption_Create_NameValidate"),
                };

                WpfMessageBox.Show(this, ref msgProperties);
                return;
            }
            int nameNum = 1;
            var argumentName = "argument";
            while (true)
            {
                if (_obsParams.Where(o => o.Name == argumentName + nameNum.ToString()).Count() == 0)
                {
                    argumentName += nameNum.ToString();
                    break;
                }
                nameNum++;
            }
            
            this._obsParams.Add(new ProjectParam()
            {
                Name = argumentName,
                Value = "",
                Description="",
                InOrOut="Input",
                ParamType=EProjectParamType.String
            });
        }

        private void paramsHeaderName_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            var paramList = new List<ProjectParam>();
            if (sort == 1)
            {
                paramList = _obsParams.OrderByDescending(o => o.Name).ToList(); 
                sort = 0;
            }
            else
            {
                paramList = _obsParams.OrderBy(o => o.Name).ToList();
                sort = 1;
            }
            _obsParams.Clear();
            paramList.ForEach(o => _obsParams.Add(o));
        }

        private void paramsHeaderDirection_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            var paramList = new List<ProjectParam>();
            if (sort == 1)
            {
                paramList = _obsParams.OrderByDescending(o => o.InOrOut).ToList();
                sort = 0;
            }
            else
            {
                paramList = _obsParams.OrderBy(o => o.InOrOut).ToList();
                sort = 1;
            }
            _obsParams.Clear();
            paramList.ForEach(o => _obsParams.Add(o));
        }

        private void paramsHeaderParamsType_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            var paramList = new List<ProjectParam>();
            if (sort == 1)
            {
                paramList = _obsParams.OrderByDescending(o => o.ParamType).ToList();
                sort = 0;
            }
            else
            {
                paramList = _obsParams.OrderBy(o => o.ParamType).ToList();
                sort = 1;
            }
            _obsParams.Clear();
            paramList.ForEach(o => _obsParams.Add(o));
        }
    }
}
